﻿using System;
using System.Collections.Generic;
using System.Text;
using Vortex.Resources;
using Vortex.Debugging;

namespace Vortex.SceneFramework {

	/// <summary>
	/// Container of domain resources bundles. It consists of common collection (shared between all of scenes) and own domain resource collection
	/// </summary>
	public class SceneResources : IResourceCollection, IDisposable {
		private DomainNode _scene;
		private ResourceCollection _sharedBundle;
		private ResourceCollection _sceneBundle;

		/// <summary>
		/// Initializes a new instance of the <see cref="SceneResources"/> class.
		/// </summary>
		/// <param name="sceneName">Name of the domain.</param>
		public SceneResources(DomainNode scene) {
			if (null == scene) throw new ArgumentNullException("scene");

			_scene = scene;

			ResourceCollection.TryLoad(@"{common}\resources.xml", out _sharedBundle);
			if (!ResourceCollection.TryLoad(string.Format(@"{{scenes}}\{0}\{0}.resources.xml", scene.Name), out _sceneBundle)) {
				//note warning
				Log.Warning("Scene '{0}' has no resources definition file", scene.Name);
			}
		}

		/// <summary>
		/// Gets the common collection for all of scenes.
		/// </summary>
		/// <value>The common collection for all of scenes.</value>
		public ResourceCollection SharedBundle {
			get { return _sharedBundle; }
		}

		/// <summary>
		/// Gets the domain own collection.
		/// </summary>
		/// <value>The domain own collection.</value>
		public ResourceCollection SceneBundle {
			get { return _sceneBundle; }
		}


		#region IResourceBundle Members

		/// <summary>
		/// Gets the resource by id. Resource should exists and be capable with type of generic argument.
		/// </summary>
		/// <typeparam name="T">Type of resource to get.</typeparam>
		/// <param name="resourceId">The resource id.</param>
		/// <returns>Resource object</returns>
		public T Get<T>(string resourceId) {
			T resource;
			if (!TryGet<T>(resourceId, out resource)) {
				throw new ResourceException("Scene '{0}' has no resource of type '{1}' and id = '{2}'", _scene.Name, typeof(T), resourceId);
			}
			return resource;			
		}

		/// <summary>
		/// Gets the resource by id. Resource may exists and be capable with type of generic argument or not.
		/// </summary>
		/// <typeparam name="T">Type of resource to get.</typeparam>
		/// <param name="resourceId">The resource id.</param>
		/// <param name="resource">The resource or default value.</param>
		/// <returns>
		/// 	<c>true</c> if resource with specified type and id exists; otherwise <c>false</c>
		/// </returns>
		public bool TryGet<T>(string resourceId, out T resource) {
			if (_sceneBundle != null && _sceneBundle.TryGet<T>(resourceId, out resource)) {
				return true;
			}
			if (_sharedBundle != null && _sharedBundle.TryGet<T>(resourceId, out resource)) {
				return true;
			}
			resource = default(T);
			return false;
		}

		#endregion

		#region IDisposable Members

		/// <summary>
		/// Frees all of bundles of this domain resources container
		/// </summary>
		public void Dispose() {
			_sharedBundle.Dispose();
			_sceneBundle.Dispose();
		}

		#endregion
	}
}
